#include "header.h"

void *write(void *ptr)
{
	int sockDesc = (int) ptr;

	//printf("Write thread CREATED with sockDesc = %d\n",sockDesc);
	
	/*
	char buffer[50]="Hello i am sending...";
	int a = send(sockDesc,&buffer,strlen(buffer),0);
	//printf("WRITE sockDesc %d Send bytes = %d buffer=%c\n",sockDesc,a,buffer[0]);
	*/
	while(1)
	{
		if(shutdownFlag == true || joinToTheNetworkFlag == true)
		{
																										//Send NOTIFY
			Header sendHeader = createHeader((uint8_t)notifyMessageType, 1);
			
			char sendheaderBuffer[28];
			memset(sendheaderBuffer,'\0',28);
			memcpy(&sendheaderBuffer[0],&htons(sendHeader.messageType),1);
			memcpy(&sendheaderBuffer[1],sendHeader.uoid,20);
			memcpy(&sendheaderBuffer[21],&htons(sendHeader.ttl),1);
			memcpy(&sendheaderBuffer[22],&htons(sendHeader.reserved),1);
			memcpy(&sendheaderBuffer[23],&htonl(sendHeader.dataLength),4);
			sendheaderBuffer[strlen(sendheaderBuffer)+1] = '\0';

			int sendHeaderBytes = send(sockDesc,&sendheaderBuffer,27,0);																				
			if(sendHeaderBytes != 27)
			{
				//printf("Header was not completely send in WRITE\n");
				pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
				deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
				close(sockDesc);
				//printf("3 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}

			char sendMessageBuffer[sendHeader.dataLength+1];
			memset(sendMessageBuffer,'\0',(sendHeader.dataLength+1)*sizeof(char));
			sendMessageBuffer[0] = '1';
			sendMessageBuffer[1] = '\0';
			
			

			int sendMsgBytes = send(sockDesc,&sendMessageBuffer,sendHeader.dataLength,0);		
			if(sendMsgBytes != (int)sendHeader.dataLength)
			{
				//printf("Msg was not completely received in WRITE\n");
				pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
				deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
				close(sockDesc);
				//printf("4 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}
			//printf("NOTIFY SENT\n");

/*
			Messages msg;
			msg.Header = (char *)malloc(28*sizeof(char));
			memset(msg.Header,'\0',28);
			//printf("A\n");
			msg.Data = (char *)malloc(512*sizeof(char));
			memset(msg.Data,'\0',512);
			//printf("B\n");
			memcpy(msg.Header, &sendheaderBuffer[0],27);
			//printf("C\n");
			memcpy(msg.Data, &sendMessageBuffer[0],1);
			//printf("D\n");
			struct timeval t;
			gettimeofday(&t, NULL);
			enterLogMessage(msg,'s',t);*/
			

			close(sockDesc);
			//printf("0 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
			pthread_exit(NULL);
		}

																					//flag set by read thread to close the socket due to no keepalive msg from neighbor
		pthread_mutex_lock(&deleteConnectionLock[sockDesc]);				
		if(deleteConnection[sockDesc] == true)
		{
			pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);	
			close(sockDesc);
			//printf("1 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
			pthread_exit(NULL);
		}
		pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);	
		


		pthread_mutex_lock(&WriteQueue[sockDesc]);													//APPLY LOCK

		
		while (writeQueue[sockDesc].size() == 0 && shutdownFlag == false)														//check if queue is empty
		{	
			pthread_cond_wait(&condition_var_Write[sockDesc], &WriteQueue[sockDesc]);									// WAIT CONDITION
			
			
			pthread_mutex_lock(&deleteConnectionLock[sockDesc]);
			if(deleteConnection[sockDesc] == true)
			{
				////printf("***********************WRITE THREAD EXIT DUE TO DUPLICATE CONNECTION***********************\n");
				close(sockDesc);
				//deleteConnection[sockDesc] = false;
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);
				pthread_mutex_unlock(&WriteQueue[sockDesc]);													//RELEASE LOCK
				//printf("2 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}
			pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);
		}

		if(shutdownFlag == true || joinToTheNetworkFlag == true)
		{
																										//Send NOTIFY
			Header sendHeader = createHeader((uint8_t)notifyMessageType, 1);
			
			char sendheaderBuffer[28];
			memset(sendheaderBuffer,'\0',28);
			memcpy(&sendheaderBuffer[0],&htons(sendHeader.messageType),1);
			memcpy(&sendheaderBuffer[1],sendHeader.uoid,20);
			memcpy(&sendheaderBuffer[21],&htons(sendHeader.ttl),1);
			memcpy(&sendheaderBuffer[22],&htons(sendHeader.reserved),1);
			memcpy(&sendheaderBuffer[23],&htonl(sendHeader.dataLength),4);
			sendheaderBuffer[strlen(sendheaderBuffer)+1] = '\0';

			int sendHeaderBytes = send(sockDesc,&sendheaderBuffer,27,0);																				
			if(sendHeaderBytes != 27)
			{
				//printf("Header was not completely send in WRITE\n");
				pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
				deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
				close(sockDesc);
				//printf("3 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}

			char sendMessageBuffer[sendHeader.dataLength+1];
			memset(sendMessageBuffer,'\0',(sendHeader.dataLength+1)*sizeof(char));
			sendMessageBuffer[0] = '1';
			sendMessageBuffer[1] = '\0';
			
			int sendMsgBytes = send(sockDesc,&sendMessageBuffer,sendHeader.dataLength,0);		
			if(sendMsgBytes != (int)sendHeader.dataLength)
			{
				//printf("Msg was not completely received in WRITE\n");
				pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
				deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
				close(sockDesc);
				//printf("4 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}
			//printf("NOTIFY SENT\n");

			close(sockDesc);
			//printf("01 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
			pthread_mutex_unlock(&WriteQueue[sockDesc]);													//RELEASE LOCK
			pthread_exit(NULL);
		}

		if(writeQueue[sockDesc].size() == 0)
		{
			pthread_mutex_unlock(&WriteQueue[sockDesc]);													//RELEASE LOCK
			continue;
		}

		
		
		Messages msg = writeQueue[sockDesc].front();
		writeQueue[sockDesc].pop_front();										// pop from this write threads queue

		pthread_mutex_unlock(&WriteQueue[sockDesc]);													//RELEASE LOCK


		
		
		char sendheaderBuffer[28];
		memset(sendheaderBuffer,'\0',28);
		memcpy(&sendheaderBuffer[0],&msg.Header[0],28);
		int sendHeaderBytes = send(sockDesc,&sendheaderBuffer,27,0);																				
		if(sendHeaderBytes != 27)
		{
			//printf("Header was not completely send in WRITE\n");
			pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
			deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
			pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
			close(sockDesc);
			//printf("3 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
			pthread_exit(NULL);
		}
		//printf("Write Thread Header Sent = %x-%x-%x-\n",sendheaderBuffer[0],sendheaderBuffer[1],sendheaderBuffer[2]);


		uint32_t dataLength;
		memcpy(&dataLength,&msg.Header[23],4);
		//printf("Write Thrread Sending Data Length = %d\n",dataLength);


		pthread_mutex_lock(&ResetKeepAlive[sockDesc]);
		resetKeepAlive[sockDesc] = true;							//msg sent hence reset the timer in keepalive thread
		pthread_mutex_unlock(&ResetKeepAlive[sockDesc]);	

		if(dataLength > 0 )
		{																							// SEND MESSAGE
			char sendMessageBuffer[dataLength];
			memset(sendMessageBuffer,'\0',(dataLength)*sizeof(char));
			memcpy(&sendMessageBuffer[0],&msg.Data[0],dataLength);
			//sendMessageBuffer[strlen(sendMessageBuffer)+1] = '\0';
			//printf("Write Thread Sent Message is : %x-%x-%x-%x\n",sendMessageBuffer[20],sendMessageBuffer[21],sendMessageBuffer[22],sendMessageBuffer[23]);
			int sendMsgBytes = send(sockDesc,&sendMessageBuffer,dataLength,0);	
			if(sendMsgBytes != (int)dataLength)
			{
				//printf("Msg was not completely received in WRITE\n");
				pthread_mutex_lock(&deleteConnectionLock[sockDesc]);													//lock
				deleteConnection[sockDesc] = true;							//set flag to tell keepalive and write to exit
				pthread_mutex_unlock(&deleteConnectionLock[sockDesc]);											//unlock
				close(sockDesc);
				//printf("4 - Write Thread EXIT due to Shutdown with sockDesc = %d\n",sockDesc);
				pthread_exit(NULL);
			}
			//printf("send bytes = %d\n",sendMsgBytes);
			//printf("SEND ---------------->= %x-%x-\n",sendMessageBuffer[22],sendMessageBuffer[23]);
			//uint16_t tempcpy;
			//memcpy(&tempcpy,&sendMessageBuffer[22],sizeof(uint16_t));
			//printf("DEBUG: tmpcpy: %u \n",tempcpy);	
				
		}
																							
		
	}
	

	return NULL;
}

